//
//  EasyChatSocketTool.swift
//  EasyChat
//
//  Created by it-go-0367 on 2021/12/17.
//

import UIKit
import CocoaAsyncSocket
import YYModel

/**
 * 目前通讯协议的内容
 * 1. 魔数 6
 * 2. 通讯协议版本号 5
 * 3. 消息本体序列化方式 1
 * 4. 消息类型 1
 * 5. 消息本体长度 4
 * 6. 消息本体 1
 * 7. 结束符号 1
 * 3 4 5 6 7
 */
class EasyChatSocketTool: NSObject {
    /** 全局单例对象*/
    static let instance : EasyChatSocketTool = EasyChatSocketTool.init()
    
    let port : UInt16 = 2022
    let host : String = "192.168.1.153"
    let magic : String = "zhuhai"
    let version : String = "1.0.1"
    var serverClient : GCDAsyncSocket?
    var clientClient : GCDAsyncSocket?
    ///有新消息过来的回调
    var newMessageColsure : (([String : AnyObject])->Void)?
    let workqueue : DispatchQueue = DispatchQueue.init(label: "socket")
    
    override init() {
        super.init()
    }
    
    func connectHost() {
        serverClient = GCDAsyncSocket.init(delegate: self, delegateQueue: workqueue)
        do {
            try serverClient?.connect(toHost: host, onPort: port)
        } catch _ {
            print("连接出现异常")
        }
    }
    
    /** 消息上报*/
    func reportInfo() {
        var msg = Data.init()
        //魔数
        msg.append(magic.data(using: .utf8)!)
        //版本号
        msg.append(version.data(using: .utf8)!)
        //消息本体序列化方式
        msg.append(Data.init(bytes: [0x01], count: 1))
        //消息类型
        msg.append(Data.init(bytes: [0x05], count: 1))
        //消息本体长度
        let message = EasyChatReportInfo.init()
        let jsonData = message.yy_modelToJSONData()
        let len : UInt32 = UInt32(jsonData!.count)
        var lenBytes : [UInt8] = [UInt8]()
        lenBytes.append(UInt8(len >> 24))
        lenBytes.append(UInt8(len >> 16))
        lenBytes.append(UInt8(len >> 8))
        lenBytes.append(UInt8(len % 255))
        msg.append(Data.init(bytes: lenBytes, count: 4))
        //消息本体
        msg.append(jsonData!)
        //结束符号
        msg.append(Data.init(bytes: [0xff], count: 1))
        
        serverClient?.write(msg, withTimeout: -1, tag: 0)
        serverClient?.readData(withTimeout: -1, tag: 0)
    }
    
    /** 私聊消息投递*/
    func sendC2CMessage(content : String, toNumber : Int) {
        var msg = Data.init()
        //魔数
        msg.append(magic.data(using: .utf8)!)
        //版本号
        msg.append(version.data(using: .utf8)!)
        //消息本体序列化方式
        msg.append(Data.init(bytes: [0x01], count: 1))
        //消息类型
        msg.append(Data.init(bytes: [0x01], count: 1))
        //消息本体长度
        let message = EasyChatC2CRequest.init()
        message.content = content
        message.fromNumber = AppDelegate.meInfo.number
        message.toNumber = toNumber
        let jsonData = message.yy_modelToJSONData()
        let len : UInt32 = UInt32(jsonData!.count)
        var lenBytes : [UInt8] = [UInt8]()
        lenBytes.append(UInt8(len >> 24))
        lenBytes.append(UInt8(len >> 16))
        lenBytes.append(UInt8(len >> 8))
        lenBytes.append(UInt8(len % 255))
        msg.append(Data.init(bytes: lenBytes, count: 4))
        //消息本体
        msg.append(jsonData!)
        //结束符号
        msg.append(Data.init(bytes: [0xff], count: 1))
        serverClient?.write(msg, withTimeout: -1, tag: 0)
    }
    
    /** 群聊消息的投递*/
    func sendGroupMessage(content : String, groupId : Int) {
        var msg = Data.init()
        //魔数
        msg.append(magic.data(using: .utf8)!)
        //版本号
        msg.append(version.data(using: .utf8)!)
        //消息本体序列化方式
        msg.append(Data.init(bytes: [0x01], count: 1))
        //消息类型
        msg.append(Data.init(bytes: [0x06], count: 1))
        //消息本体长度
        let message = EasyChatGroupRequest.init()
        message.groupID = groupId
        message.content = content
        message.fromNumber = AppDelegate.meInfo.number
        let jsonData = message.yy_modelToJSONData()
        let len : UInt32 = UInt32(jsonData!.count)
        var lenBytes : [UInt8] = [UInt8]()
        lenBytes.append(UInt8(len >> 24))
        lenBytes.append(UInt8(len >> 16))
        lenBytes.append(UInt8(len >> 8))
        lenBytes.append(UInt8(len % 255))
        msg.append(Data.init(bytes: lenBytes, count: 4))
        //消息本体
        msg.append(jsonData!)
        //结束符号
        msg.append(Data.init(bytes: [0xff], count: 1))
        serverClient?.write(msg, withTimeout: -1, tag: 0)
    }
    
    /** 设置新消息过来时候的回调*/
    func setNewMessageColsure(colsure : @escaping (([String : AnyObject])->Void)) {
        newMessageColsure = colsure
    }
}
extension EasyChatSocketTool: GCDAsyncSocketDelegate {

    /** 连接成功的回调*/
    func socket(_ sock: GCDAsyncSocket, didConnectToHost host: String, port: UInt16) {
        print("已经连接上服务器: ", host, ":", port)
        //连接上服务器以后，上报自身的number
        reportInfo()
    }
    
    func socketDidDisconnect(_ sock: GCDAsyncSocket, withError err: Error?) {
        print("未连接上服务器")
    }
    
    /** 数据发送成功的回调*/
    func socket(_ sock: GCDAsyncSocket, didWriteDataWithTag tag: Int) {
        print("数据发送成功, Tag: ", tag)
    }
    
    /** 接收到服务端消息的回调*/
    func socket(_ sock: GCDAsyncSocket, didRead data: Data, withTag tag: Int) {
        //let msg = String.init(data: data, encoding: .utf8)
        guard let json = try? JSONSerialization.jsonObject(with: data, options: .mutableContainers) else {
             return
        }
        let value : [String : AnyObject] = json as! [String : AnyObject]
        if newMessageColsure != nil {
            newMessageColsure!(value)
        }
        serverClient?.readData(withTimeout: -1, tag: 0)
    }
    

}
